﻿using Amazon.S3.Model;
using Microsoft.AspNetCore.Mvc;
using Nasty.Core.Authorization;
using Nasty.Core.Entity.System;
using Nasty.Core.LoadParams;
using Nasty.Core.Model;
using Nasty.Core.Registry;
using Nasty.Core.Session;
using Nasty.SystemModule.Areas.User.Model;
using Nasty.SystemModule.Areas.User.Params;
using System.Security.Principal;


namespace Nasty.SystemModule.User
{
    public interface IUserService : IAutofacRegister
    {
        public Nasty.Core.Entity.System.User GetUser(string id);

        public ResultData<Nasty.Core.Entity.System.User> SaveUser(UserModel model);

        public ResultData<UserInfoModel> Login(LoginParams @params);

        public ResultData<UserInfoModel> GetCurrentUserInfo();

        public PageData<Nasty.Core.Entity.System.User> GetUserPage(GetUserPageParams @params);

        public ResultData<string> InitSA(string password);

        public ResultData<string> SaveUserRole(SaveUserRoleModel model);

        public ResultData<string> DeleteUser(string id);

        public List<Nasty.Core.Entity.System.User> GetUsers(GetUsersParams @params);
    }

    public class UserService : IUserService
    {
        public required IUserRepository UserRepository { get; set; }

        public List<Nasty.Core.Entity.System.User> GetUsers(GetUsersParams @params)
        {
            return UserRepository.GetUsers(@params);
        }

        public ResultData<string> DeleteUser(string id)
        {
            return UserRepository.DeleteUser(id);
        }

        public Nasty.Core.Entity.System.User GetUser(string id)
        {
            return UserRepository.GetUser(id);
        }

        public ResultData<Nasty.Core.Entity.System.User> SaveUser(UserModel model)
        {
            var result = UserRepository.SaveUser(model);
            MakeUserInfo(model.Id);
            return result;
        }

        public ResultData<UserInfoModel> GetCurrentUserInfo()
        {
            var result = new ResultData<UserInfoModel>();
            var account = AppSession.CurrentUser?.Value?.Account ?? string.Empty;
            var info = TryRefreshToken(account);
            result.Data = info;
            result.IsSuccess = true;
            return result;
        }

        public ResultData<UserInfoModel> Login(LoginParams @params)
        {
            var result = new ResultData<UserInfoModel>();
            var user = UserRepository.GetUserByAccount(@params.Account, Core.Tools.Md5(@params.Password));
            if (user == null)
            {
                result.IsSuccess = false;
                return result;
            }

            var info = MakeUserInfo(user.Id);
            result.Data = info;
            result.IsSuccess = true;
            return result;
        }

        private UserInfoModel MakeUserInfo(string id)
        {
            var user = UserRepository.GetDeepUser(id);
            var roles = ((user.Roles?.Select(x => x.Code).ToArray()) as string[]) ?? Array.Empty<string>();
            var permissions = (user.Roles.Where(t => t.Permissions != null).SelectMany((t) => t.Permissions).Select((t) => t.Code).ToArray() as string[]) ?? Array.Empty<string>();
            var deptRoles = user.Departments?.Where(t => t.Role != null).Select((t) => t.Role).ToList() ?? new List<Nasty.Core.Entity.System.Role?>();
            var deptRolesCode = deptRoles.Select(x => x.Code).ToArray() as string[] ?? Array.Empty<string>();
            var deptPermissions = deptRoles.Where(t => t.Permissions != null).SelectMany((t) => t.Permissions).Select((t) => t.Code).ToArray() as string[] ?? Array.Empty<string>();

            roles = roles.Union(deptRolesCode).ToArray();
            permissions = permissions.Union(deptPermissions).ToArray();

            var info = new UserInfoModel();
            info.Id = user.Id;
            info.Token = Auth.MakeToken(user.Account, 3);
            info.Account = user.Account;
            info.Name = user.Name;
            info.MobileNumber = user.MobileNumber;
            info.Email = user.Email;
            info.Introduction = user.Introduction;
            info.Avatar = user.Avatar;
            info.Roles = roles;
            info.Permissions = permissions;
            if (user.MainDepartment != null) info.MainDepartment = new IdNameModel() { Id = user.MainDepartment?.Id, Name = user.MainDepartment?.Name, Code = user.MainDepartment.Code };
            info.Departments = (user.Departments ?? new List<Core.Entity.System.Department>()).Select((t) => new IdNameModel() { Id = t.Id, Name = t.Name, Code = user.MainDepartment.Code }).ToList();

            SessionManager.SetUserInfo(user.Account, info);
            Auth.MakeCookie(user.Account, 3);

            return info;
        }

        public UserInfoModel? TryRefreshToken(string account)
        {
            var info = SessionManager.GetUserInfo(account);
            if (info == null) return null;

            var isAboutExpire = Auth.IsAboutExpire(info.Token);
            if (!isAboutExpire) return info;


            info.Token = Auth.MakeToken(info.Account, 3);
            SessionManager.SetUserInfo(info.Account, info);
            Auth.MakeCookie(info.Account, 3);
            return info;
        }

        public ResultData<string> InitSA(string password)
        {
            return UserRepository.InitSA(password);
        }

        public ResultData<string> SaveUserRole(SaveUserRoleModel model)
        {
            var result = UserRepository.SaveUserRole(model);
            MakeUserInfo(model.UserId);
            return result;
        }

        public PageData<Nasty.Core.Entity.System.User> GetUserPage(GetUserPageParams @params)
        {
            return UserRepository.GetUserPage(@params);
        }
    }
}
